using System;
using System.Collections.Generic;
using System.Web;

namespace PS.WebParts.Rollup.Query
{
    public interface ICacheProvider
    {
        //void Add(CacheItemKey key, List<DBList> lists, Dictionary<string, string> fields);
        //bool Contains(CacheItemKey key);
        //void Get(CacheItemKey key, out List<DBList> lists, out Dictionary<string, string> fields);

        void AddListFields(Guid listId, Dictionary<string, string> fields);
        bool ContainsListFields(Guid listId);
        void GetListFields(Guid listId, out Dictionary<string, string> fields);

        void CacheString(Guid id, string value);
        bool ContainsString(Guid id);
        string GetString(Guid id);

        object this[string key] { get; set;}
        bool ContainsKey(string key);

    }

    //public class CacheItemKey : IComparable<CacheItemKey>, IEquatable<CacheItemKey>
    //{
    //    private int userID;
    //    private RollUpQueryWebScope scope;
    //    private Guid webId;
    //    private string webRelativeUrl;

    //    public CacheItemKey(int userID, RollUpQueryWebScope scope, Guid webId, string webRelativeUrl)
    //    {
    //        this.userID = userID;
    //        this.scope = scope;
    //        this.webId = webId;
    //        this.webRelativeUrl = webRelativeUrl;
    //    }

    //    [DebuggerHidden()]
    //    public int UserID
    //    {
    //        get { return userID; }
    //        set { userID = value; }
    //    }

    //    [DebuggerHidden()]
    //    public RollUpQueryWebScope Scope
    //    {
    //        get { return scope; }
    //        set { scope = value; }
    //    }

    //    [DebuggerHidden()]
    //    public Guid WebId
    //    {
    //        get { return webId; }
    //        set { webId = value; }
    //    }

    //    [DebuggerHidden()]
    //    public string WebRelativeUrl
    //    {
    //        get { return webRelativeUrl; }
    //        set { webRelativeUrl = value; }
    //    }


    //    public int CompareTo(CacheItemKey other)
    //    {
    //        if (userID == other.userID)
    //        {
    //            if(scope == other.scope)
    //            {
    //                if(webId == other.webId)
    //                {
    //                    return webRelativeUrl.CompareTo(other.webRelativeUrl);
    //                }
    //                else
    //                {
    //                    return webId.CompareTo(other.webId);
    //                }
    //            }
    //            else
    //            {
    //                return scope.CompareTo(other.scope);
    //            }
    //        }
    //        else
    //        {
    //            return userID.CompareTo(other.userID);
    //        }
    //    }

    //    public override string ToString()
    //    {
    //        return string.Format("{0} : {1} : {2} : {3}", userID, scope, webId, webRelativeUrl);
    //    }

    //    public bool Equals(CacheItemKey other)
    //    {
    //        return CompareTo(other) == 0;
    //    }

    //    public override int GetHashCode()
    //    {
    //        return ToString().GetHashCode();
    //    }
    //}

    public class PSSiteDataSchemaCache : ICacheProvider
    {
        private Dictionary<Guid, Dictionary<string, string>> cache = new Dictionary<Guid, Dictionary<string, string>>();
        private Dictionary<Guid, string> stringCache = new Dictionary<Guid, string>();
        private Dictionary<string, object> objCache = new Dictionary<string, object>();

        public void AddListFields(Guid listId, Dictionary<string, string> fields)
        {
            cache[listId] = fields;
        }

        public bool ContainsListFields(Guid listId)
        {
            return cache.ContainsKey(listId);
        }

        public void GetListFields(Guid listId, out Dictionary<string, string> fields)
        {
            if(ContainsListFields(listId))
            {
                fields = cache[listId];
            }
            else
            {
                fields = null;
            }
        }

        public void CacheString(Guid id, string value)
        {
            stringCache[id] = value;
        }

        public bool ContainsString(Guid id)
        {
            return stringCache.ContainsKey(id);
        }

        public string GetString(Guid id)
        {
            if (stringCache.ContainsKey(id))
                return stringCache[id];
            else
                return null;
        }

        public object this[string key]
        {
            get
            {
                return objCache[key];
            }
            set
            {
                objCache[key] = value;
            }
        }

        public bool ContainsKey(string key)
        {
            return objCache.ContainsKey(key);
        }

        public void Clear()
        {
            cache.Clear();
            stringCache.Clear();
            objCache.Clear();
        }
    }

    //internal class ItemPair
    //{
    //    private List<DBList> lists;
    //    private Dictionary<string, string> fields;

    //    public ItemPair(List<DBList> lists, Dictionary<string, string> fields)
    //    {
    //        this.Lists = lists;
    //        this.Fields = fields;
    //    }

    //    public List<DBList> Lists
    //    {
    //        get { return lists; }
    //        set { lists = value; }
    //    }

    //    public Dictionary<string, string> Fields
    //    {
    //        get { return fields; }
    //        set { fields = value; }
    //    }
    //}

    public class AspNetDataSchemaCache : ICacheProvider
    {
        private HttpContext ctx;

        public AspNetDataSchemaCache()
        {
            ctx = HttpContext.Current;
        }

        public AspNetDataSchemaCache(HttpContext context)
        {
            ctx = context;
        }
        
        //public void Add(CacheItemKey key, List<DBList> lists, Dictionary<string, string> fields)
        //{
        //    ctx.Cache[key.ToString()] = new ItemPair(lists, fields);
        //}

        //public bool Contains(CacheItemKey key)
        //{
        //    return (ctx.Cache[key.ToString()] != null);
        //}

        //public void Get(CacheItemKey key, out List<DBList> lists, out Dictionary<string, string> fields)
        //{
        //    if(Contains(key))
        //    {
        //        ItemPair item = (ItemPair) ctx.Cache[key.ToString()];
        //        lists = item.Lists;
        //        fields = item.Fields;
        //    }
        //    else
        //    {
        //        lists = null;
        //        fields = null;
        //    }
        //}

        public void AddListFields(Guid listId, Dictionary<string, string> fields)
        {
            ctx.Cache[listId.ToString("D")] = fields;
        }

        public bool ContainsListFields(Guid listId)
        {
            return (ctx.Cache[listId.ToString("D")] != null);
        }

        public void GetListFields(Guid listId, out Dictionary<string, string> fields)
        {
            if(ContainsListFields(listId))
            {
                fields = (Dictionary<string, string>)ctx.Cache[listId.ToString()];
            }
            else
            {
                fields = null;
            }
        }

        public void CacheString(Guid id, string value)
        {
            ctx.Cache[id.ToString("D")] = value;
        }

        public bool ContainsString(Guid id)
        {
            return (ctx.Cache[id.ToString("D")] != null);
        }

        public string GetString(Guid id)
        {
            if (ContainsString(id))
                return (string)ctx.Cache[id.ToString("D")];
            else
                return null;
        }

        public object this[string key]
        {
            get
            {
                return ctx.Cache[key];
            }
            set
            {
                ctx.Cache[key] = value;
            }
        }

        public bool ContainsKey(string key)
        {
            return (ctx.Cache[key] != null);
        }
    }


    public class CacheSingleton
    {
        private static readonly ICacheProvider instance = new PSSiteDataSchemaCache();

        // Explicit static constructor to tell C# compiler
        // not to mark type as beforefieldinit
        static CacheSingleton()
        {
        }

        private CacheSingleton()
        {
        }

        public static ICacheProvider Instance
        {
            get
            {
                return instance;
            }
        }
    }
}
